﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace CWM.Skinn
{
    public static partial class SkinnContextCommands
    {
        [CtxMenuItem("SkinnedMeshRenderer/SubMesh/Combine/Merge Shared",
            "Submeshes with matching materials are combined.",
            ContextRequirements.SingleItem, 0)]
        public static void SkinnedMeshRendererCombineSingle() { SkinnedMeshCombine(true); }

        [CtxMenuItem("SkinnedMeshRenderer/SubMesh/Combine/Selection/Merge Shared",
            "Merge Selected Meshes into one mesh. " +
            "Sources are disable and a new renderer is created. " +
            "Submeshes with matching materials are combined.",
            ContextRequirements.MultipleItems, 0)]
        public static void SkinnedMeshRendererCombine() { SkinnedMeshCombine(true); }

        [CtxMenuItem("SkinnedMeshRenderer/SubMesh/Combine/Selection/Keep Shared",
            "Merge Selected Meshes into one mesh. " +
            "Sources are disable and a new renderer is created. " +
            "All meshes are keep as submeshes.",
            ContextRequirements.MultipleItems, 0)]
        public static void RendererCombineKeep(){SkinnedMeshCombine(false);}

        [CtxMenuItem("MeshRenderer/SubMesh/Combine/Merge Shared",
            "Submeshes with matching materials are combined and removed.",
            ContextRequirements.SingleItem, 0)]
        public static void MeshRendererCombineSingle() { MeshRendererCombine(true); }

        [CtxMenuItem("MeshRenderer/SubMesh/Combine Selection/Merge Shared",
            "Merge Selected Meshes into one mesh. " +
            "Sources are disable and a new renderer is created. " +
            "Submeshes with matching materials are combined.",
            ContextRequirements.MultipleItems, 0)]
        public static void MeshRendererCombine(){ MeshRendererCombine(true);}

        [CtxMenuItem("MeshRenderer/SubMesh/Combine Selection/Keep Shared",
            "Merge Selected Meshes into one mesh. " +
            "Sources are disable and a new renderer is created. " +
            "All meshes are keep as submeshes.",
            ContextRequirements.MultipleItems, 0)]
        public static void MeshRendererCombineKeep() { MeshRendererCombine(false); }

        public static GameObject MeshRendererCombine(bool mergeMaterials)
        {
            Transform root = null;
            Transform isRoot = null;
            var sources = new List<Renderer>();
            foreach (var item in SkinnContext.GetContextItems())
            {
                var context = item.GetComponent<MeshRenderer>();
                if (SkinnEx.IsNullOrNotInAScene(context)) continue;
                if (!SkinnEx.HasMinimumRequirements(context)) continue;
                isRoot = context.transform.root;
                if (root == null || root == isRoot) root = isRoot;
                sources.Add(context);
                SkinnContext.UndoRecord(context, "Combine MeshRenderers");
                context.gameObject.SetActive(false);
            }
            if (sources.Count < 1) { SkinnContext.LogWarning("not enough valid meshes to combine!"); return null; }
            var renderer = sources.ToArray().CombinedStaticMeshes(mergeMaterials);
            if (!renderer) { SkinnContext.LogWarning("not enough valid meshes to combine! error!"); return null; }

            var name = isRoot == root ? root.name + "_" : "_" ;
            name += renderer.sharedMaterials.Length > 1 ? "Combined Mesh" : "Combined SubMeshes";

            renderer.transform.SetParent(root.parent);

            Undo.RegisterCreatedObjectUndo(renderer.gameObject, "Combine MeshRenderers");

            Selection.objects = new Object[] { renderer.gameObject };

            SkinnContext.Finished();

            return renderer.gameObject;
        }

        public static GameObject SkinnedMeshCombine(bool mergeMaterials)
        {
            Transform root = null;
            Transform isRoot = null;
            var sources = new List<Renderer>();
            foreach (var item in SkinnContext.GetContextItems())
            {
                var context = item.GetComponent<SkinnedMeshRenderer>();
                if (SkinnEx.IsNullOrNotInAScene(context)) continue;
                if (!SkinnEx.HasMinimumRequirements(context)) continue;
                isRoot = context.transform.root;
                if (isRoot != null || root == isRoot) root = isRoot;
                sources.Add(context);
                SkinnContext.UndoRecord(context, "Combine SkinnedMeshes");
                context.gameObject.SetActive(false);
            }
            if (sources.Count < 1) { SkinnContext.LogWarning("not enough valid meshes to combine!"); return null; }
            var renderer = sources.ToArray().CombinedMeshes(mergeMaterials);
            if (!renderer) { SkinnContext.LogWarning("not enough valid meshes to combine! error!"); return null; }

            var name = isRoot == root ? root.name + "_" : "_";
            name += renderer.sharedMaterials.Length > 1 ? "Combined Mesh" : "Combined SubMeshes";

            Undo.RegisterCreatedObjectUndo(renderer.gameObject, "Combine SkinnedMeshes");
            renderer.gameObject.name = name;
            renderer.transform.SetParent(isRoot);
            Selection.objects = new Object[] { renderer.gameObject };

            SkinnContext.Finished();

            return renderer.gameObject;
        }
    }
}